<!-- @format --> <script lang="ts" setup> import { ArrowRight } from '@element-plus/icons-vue' import { Swiper, SwiperSlide } from 'swiper/vue' import { Navigation, Pagination } from 'swiper/modules' import dayjs from 'dayjs' import { ConstKeys } from '~/enums/const-enums' import { PageSizeEnum } from '~/enums/sizeEnum' import { getFeatureAlumDetailApi, getFeatureBrandsListApi, getFeatureDetailApi, getFeatureGoodsListApi, } from '~/api/model/feature' import img02 from '~/assets/images/featured_img02.png' import img03 from '~/assets/images/featured_img03.png' import img04 from '~/assets/images/featured_img04.png' import img05 from '~/assets/images/featured_img05.png' import 'swiper/css' import 'swiper/css/navigation' // import "swiper/css/pagination" import { useUserStore } from '@/stores/modules/user' enum Type { Detail = '0', Album = '1', } const userStore = useUserStore() const { isLogin } = storeToRefs(userStore) const { openLoginModal } = useLoginModal() const modules = [Navigation, Pagination] const brandList = ref<any>([]) const swiperVertical = ref<any>(null) const detail = ref() const list = ref<any>([]) const currentPage = ref(0) const total = ref(0) const page_size = ref(20) const isEffective = ref(true) const staticList = ref([ { icon: img02, title: 'Source Manufacturers', subTitle: 'Selected product suppliers with the capability to develop unique products.', }, { icon: img03, title: 'Competitive Pricing', subTitle: 'Get the best quality products at the most competitive wholesale prices.', }, { icon: img04, title: 'Strict Quality Control', subTitle: 'Strict quality inspection to ensure the products meet our high standards.', }, { icon: img05, title: 'Dedicated Support', subTitle: 'Smooth wholesale experience with dedicated customer manager service.', }, ]) const route = useRoute() const paintingId = route.query.paintingId const slug = route.params.name const { data, pending, error, refresh } = await useAsyncData( 'featured-detail', () => $fetch(`${ConstKeys.DOMAINPRO}/client/topic/detail`, { params: { slug } }), ) const seoData = data.value?.result useHead({ title: seoData?.title, meta: [ { name: 'description', content: seoData?.headImageText, }, { property: 'og:title', content: seoData?.title, }, { property: 'og:description', content: seoData?.headImageText, }, { property: 'og:type', content: 'website', }, { property: 'twitter:title', content: seoData?.title, }, { property: 'twitter:description', content: seoData?.headImageText, }, { property: 'twitter:card', content: 'summary_large_image', }, ], link: [ { rel: 'canonical', href: `${ConstKeys.DOMAINPRO}/collections/${slug}`, }, ], }) const isType = computed(() => detail.value?.type === Type.Detail) async function getFeatureDetail() { try { const result = await getFeatureDetailApi({ slug }) detail.value = result } catch (error) { console.log('error', error) } } async function getFeatureAlumDetail() { try { const result = await getFeatureAlumDetailApi({ paintingId }) isEffective.value = true detail.value = result } catch (error: any) { if (error.code === 10010) isEffective.value = false console.log('error', error) } } async function getFeatureProductList( pageNo = PageSizeEnum.PAGE, pageSize = page_size.value, ) { const res: any = await getFeatureGoodsListApi({ pageNo, pageSize, topicSlug: slug, }) list.value = res.records currentPage.value = res.current total.value = res.total } function updatePage(currentPage: number, pageSize: number) { getFeatureProductList(currentPage, pageSize) } async function getHomeBrandList() { try { const data: any = await getFeatureBrandsListApi({ pageNo: 1, pageSize: page_size.value, topicSlug: slug, }) brandList.value = data.records } catch (error) { console.log('error', error) } } function onVerticalSwiper(swiper: any) { swiperVertical.value = swiper } function onClickLeft() { swiperVertical.value.slidePrev() } function onClickRight() { swiperVertical.value.slideNext() } function getData() { if (!paintingId) { getHomeBrandList() getFeatureProductList() getFeatureDetail() } else { getFeatureAlumDetail() } } getData() async function openLogin() { await openLoginModal() } </script> <template> <div class="pos-relative"> <div v-if="isType" class="fixed-image"> <img :src="detail?.headImageUrl" class="w-full h-360px object-cover" alt="" srcset="" > </div> <div class="scrollable-content"> <div v-if="isType" :class="isType ? 'h-360px' : ''" class="content-header" > <h1 class="!text-36px !fw-700 custom-title-font"> {{ detail?.title }} </h1> <div class="text-18px"> {{ detail?.headImageText }} </div> </div> <div :class="isType ? 'bg-#fff' : ''"> <div v-if="isEffective" class="w-1400px mx-auto pt-40px pb-60px"> <el-breadcrumb :separator-icon="ArrowRight"> <el-breadcrumb-item :to="{ path: '/' }"> Home </el-breadcrumb-item> <el-breadcrumb-item :to="{ path: '/collections' }"> Collections </el-breadcrumb-item> <el-breadcrumb-item> {{ detail?.title }}</el-breadcrumb-item> </el-breadcrumb> </div> <div v-if="isEffective" class="w-1400px mx-auto mb-60px"> <h1 class="!text-26px !fw-700 text-#363C40 custom-title-font"> {{ detail?.title }} </h1> <div class="flex my-24px text-#7C7C7C text-18px"> <div class="mr-48px"> {{ dayjs(detail?.createTime).format('MMMM D, YYYY') }} </div> <div v-if="isType"> {{ detail?.merchandiseQuantity }} products </div> </div> <div class="text-18px lh-24px line-clamp-3 text-#666" :title="detail?.headImageText" > {{ detail?.headImageText }} </div> </div> <div> <div v-if="isType"> <div v-if="isLogin || !detail?.userEnable" class="w-1400px mx-auto pb-160px" > <div v-if="list.length" class="grid grid-gap-x-65px grid-gap-y-80px grid-cols-4" > <div v-for="item in list" :key="item.id"> <common-goods-item :item /> </div> </div> <common-empty v-else class="py-50px" title=""> <template #icon> <img src="~/assets/images/featured_empty.png" class="w-200px h-200px" alt="" srcset="" > </template> </common-empty> <div v-if="list.length" class="mt-60px flex justify-center"> <el-pagination v-model:current-page="currentPage" :page-size="page_size" :pager-count="10" layout="prev, pager, next" :total="total" @change="updatePage" /> </div> </div> <div v-else class="w-1400px mx-auto pt-80px pb-160px flex justify-center" > <div class="cursor-pointer" @click="openLogin"> <svgo-lock class="!w-100px !h-100px text-#999 m-auto" /> <div class="text-#999 text-42px mt-20px"> Login to view </div> </div> </div> </div> <div v-else class="text-#000 w-1400px mx-auto pb-160px"> <div v-if="isEffective" class="text-#333333 content-detail custom-html" v-html="detail?.content" /> <div v-else class="pt-160px"> Sorry, the shared content has expired. </div> </div> <div v-if="isType" class="flex justify-center items-center py-82px bg-#FAF5F1" > <div class="w-600px"> <h2 class="fw-700 text-32px text-#333 !mb-60px"> Quality Wholesale, Inspiring Global Retail </h2> <div v-for="(item, index) in staticList" :key="index" class="flex items-center mb-40px last:mb-0" > <img :src="item.icon" alt="" srcset="" class="w-40px h-40px"> <div class="ml-30px w-430px"> <h3 class="!fw-500 text-26px text-#333 lh-30px"> {{ item.title }} </h3> <div class="mt-10px text-18px text-#999 lh-28px"> {{ item.subTitle }} </div> </div> </div> </div> <img src="~/assets/images/featured_img01.png" class="w-566px h-480px object-cover ml-10px" alt="" srcset="" > </div> <div v-if="isType" class="py-160px w-1400px mx-auto"> <h2 class="!mb-40px fw-700 text-40px text-#363C40"> Collection Brands </h2> <div v-if="brandList.length"> <div class="w-1300px mx-auto pos-relative"> <div class="pos-absolute cursor-pointer left--46px top-200px w-28px h-28px transform-translate-y--50% cursor-not-allowed !cursor-pointer flex justify-center items-center" @click="onClickLeft()" > <img src="~/assets/images/arrow_left.png" alt="" class="w-26px h-26px" srcset="" > </div> <div class="pos-absolute cursor-pointer right--46px top-200px w-28px h-28px transform-translate-y--50% cursor-not-allowed !cursor-pointer flex justify-center items-center" @click="onClickRight()" > <img src="~/assets/images/arrow_right.png" alt="" class="w-26px h-26px" srcset="" > </div> <Swiper :slides-per-view="4" :space-between="55" :modules="modules" :loop="true" :navigation="false" :pagination="true" class="pos-relative" @swiper="onVerticalSwiper" > <SwiperSlide v-for="(item, index) in brandList" :key="index"> <common-brand-item :item="item" /> </SwiperSlide> </Swiper> </div> </div> <common-empty v-else class="pt-50px" title=""> <template #icon> <img src="~/assets/images/featured_empty.png" class="w-200px h-200px" alt="" srcset="" > </template> </common-empty> </div> </div> </div> <AppFooter class="bg-#fff" /> </div> </div> </template> <style lang="less" scoped> .fixed-image { position: fixed; top: 151px; left: 0; width: 100%; height: 360px; z-index: 1; overflow: hidden; } .scrollable-content { position: relative; z-index: 2; width: 100%; color: white; .content-header { display: flex; // height: 360px; flex-direction: column; justify-content: center; align-items: center; text-align: center; background: rgba(0, 0, 0, 0.4); /* 半透明背景使文字在图片上更可读 */ } ::v-deep(.content-detail) { font-family: sans-serif; h2 { font-size: 1.5em; font-family: 'CustomTitleFont'; margin-top: 1em !important; margin-bottom: 1em !important; font-weight: bold; } h3 { display: block; font-size: 1.17em; margin-block-start: 1em; margin-block-end: 1em; margin-inline-start: 0px; margin-inline-end: 0px; margin-bottom: 1em !important; font-weight: bold; unicode-bidi: isolate; font-family: 'CustomTitleFont'; } p { display: block; margin-block-start: 1em; margin-block-end: 1em; margin-inline-start: 0px; margin-inline-end: 0px; unicode-bidi: isolate; } ul { display: block; list-style-type: disc; margin-block-start: 1em; margin-block-end: 1em; margin-inline-start: 0px; margin-inline-end: 0px; padding-inline-start: 40px; unicode-bidi: isolate; li { display: list-item; text-align: -webkit-match-parent; unicode-bidi: isolate; } } ol { list-style-type: decimal; display: block; list-style-type: decimal; margin-block-start: 1em; margin-block-end: 1em; margin-inline-start: 0px; margin-inline-end: 0px; padding-inline-start: 40px; unicode-bidi: isolate; } } } </style>